home *** CD-ROM | disk | FTP | other *** search
/ Alles Voor Internet / Tout Pour Internet / alles voor internet.iso / MacInternet™ / Telnet / zmodem-part4-unix.shar / sz.c
C/C++ Source or Header  |  1993-10-23  |  44KB  |  2,096 lines

  1. #define VERSION "sz 3.03 5-09-89"
  2. #define PUBDIR "/usr/spool/uucppublic"
  3.  
  4. /*% cc -compat -M2 -Ox -K -i -DTXBSIZE=16384  -DNFGVMIN -DREADCHECK
  5. sz.c -lx -o sz; size sz
  6.  
  7. /*% cc -Zi -DXX -DNFGVMIN -DREADCHECK sz.c -lx -o xsz; size xsz
  8. <-xtx-*> cc -Osal -DTXBSIZE=32768  -DSV sz.c -lx -o $B/sz; size $B/sz
  9.  
  10.  ****************************************************************************
  11.  *
  12.  * sz.c By Chuck Forsberg,  Omen Technology INC
  13.  *
  14.  ****************************************************************************
  15.  *
  16.  * Typical Unix/Xenix/Clone compiles:
  17.  *
  18.  *    cc -O sz.c -o sz        USG (SYS III/V) Unix
  19.  *    cc -O -DSV sz.c -o sz        Sys V Release 2 with non-blocking input
  20.  *                    Define to allow reverse channel checking
  21.  *    cc -O -DV7  sz.c -o sz        Unix Version 7, 2.8 - 4.3 BSD
  22.  *
  23.  *    cc -O -K -i -DNFGVMIN -DREADCHECK sz.c -lx -o sz    Classic Xenix
  24.  *
  25.  *    ln sz sb            **** All versions ****
  26.  *    ln sz sx            **** All versions ****
  27.  *
  28.  ****************************************************************************
  29.  *
  30.  * Typical VMS compile and install sequence:
  31.  *
  32.  *        define LNK$LIBRARY   SYS$LIBRARY:VAXCRTL.OLB
  33.  *        cc sz.c
  34.  *        cc vvmodem.c
  35.  *        link sz,vvmodem
  36.  *    sz :== $disk$user2:[username.subdir]sz.exe
  37.  *
  38.  *  If you feel adventureous, remove the #define BADSEEK line
  39.  *  immediately following the #ifdef vax11c line!  Some VMS
  40.  *  systems know how to fseek, some don't.
  41.  *
  42.  ****************************************************************************
  43.  *
  44.  *
  45.  * A program for Unix to send files and commands to computers running
  46.  *  Professional-YAM, PowerCom, YAM, IMP, or programs supporting Y/XMODEM.
  47.  *
  48.  *  Sz uses buffered I/O to greatly reduce CPU time compared to UMODEM.
  49.  *
  50.  *  USG UNIX (3.0) ioctl conventions courtesy Jeff Martin
  51.  *
  52.  *    This version implements ZMODEM Run Length Encoding, Comparision,
  53.  *    and variable length headers.  These features were not funded
  54.  *    by the original Telenet development contract.  This software,
  55.  *    including these features, may be freely used for non
  56.  *    commercial and educational purposes.  This software may also
  57.  *    be freely used to support file transfer operations to or from
  58.  *    licensed Omen Technology products.  Contact Omen Technology
  59.  *    for licensing for other uses.  Any programs which use part or
  60.  *    all of this software must be provided in source form with this
  61.  *    notice intact except by written permission from Omen
  62.  *    Technology Incorporated.
  63.  *
  64.  *        Omen Technology Inc        FAX: 503-621-3745
  65.  *        Post Office Box 4681
  66.  *        Portland OR 97208
  67.  *
  68.  *    Previous versions of this program (not containing the extensions
  69.  *    listed above) remain in the public domain.
  70.  *
  71.  *    This code is made available in the hope it will be useful,
  72.  *    BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
  73.  *    DAMAGES OF ANY KIND.
  74.  *
  75.  *  2.1x hacks to avoid VMS fseek() bogosity, allow input from pipe
  76.  *     -DBADSEEK -DTXBSIZE=32768  
  77.  *  2.x has mods for VMS flavor
  78.  *
  79.  * 1.34 implements tx backchannel garbage count and ZCRCW after ZRPOS
  80.  * in accordance with the 7-31-87 ZMODEM Protocol Description
  81.  */
  82.  
  83. #ifdef XX
  84. #define XARGSFILE "args"
  85. long Thisflen;
  86. #endif
  87.  
  88. char *substr(), *getenv();
  89.  
  90. #ifdef vax11c
  91. #define STATIC
  92. #define BADSEEK
  93. #define TXBSIZE 32768        /* Must be power of two, < MAXINT */
  94. #include <types.h>
  95. #include <stat.h>
  96. #define STAT
  97. #define LOGFILE "szlog.tmp"
  98. #include <stdio.h>
  99. #include <signal.h>
  100. #include <setjmp.h>
  101. #include <ctype.h>
  102. #include <errno.h>
  103. #define OS "VMS"
  104. #define ROPMODE "r"
  105. #define READCHECK
  106. #define BUFWRITE
  107. extern int errno;
  108. #define SS_NORMAL SS$_NORMAL
  109. #define xsendline(c) sendline(c)
  110.  
  111. #ifndef PROGNAME
  112. #define PROGNAME "sz"
  113. #endif
  114.  
  115.  
  116. #else    /* vax11c */
  117.  
  118. #ifdef GENIE
  119. #define STATIC static
  120. #define LOGFILE "szlog"
  121. #define BADSEEK
  122. #define TXBSIZE 32768        /* Must be power of two, < MAXINT */
  123. #define OS "GEnie"
  124. #define SS_NORMAL 0
  125. #include <stdio.h>
  126. #include <signal.h>
  127. #include <setjmp.h>
  128. #include <ctype.h>
  129. #include <errno.h>
  130. #include <stdlib.h>
  131. #include <fildes.h>
  132. FILDES fdes;
  133. extern int errno;
  134. int Binfile;
  135. long Thisflen;
  136.  
  137. #define sendline(c) putchar(c & 0377)
  138. #define xsendline(c) putchar(c)
  139.  
  140. #else    /* GENIE */
  141.  
  142. #define LOGFILE "/tmp/szlog"
  143. #define SS_NORMAL 0
  144. #include <stdio.h>
  145. #include <signal.h>
  146. #include <setjmp.h>
  147. #include <ctype.h>
  148. #include <errno.h>
  149. extern int errno;
  150. #define STATIC
  151.  
  152. #define sendline(c) putchar(c & 0377)
  153. #define xsendline(c) putchar(c)
  154.  
  155. #endif
  156. #endif
  157.  
  158. #define PATHLEN 256
  159. #define OK 0
  160. #define FALSE 0
  161. #ifdef TRUE
  162. #undef TRUE
  163. #endif
  164. #define TRUE 1
  165. #define ERROR (-1)
  166. /* Ward Christensen / CP/M parameters - Don't change these! */
  167. #define ENQ 005
  168. #define CAN ('X'&037)
  169. #define XOFF ('s'&037)
  170. #define XON ('q'&037)
  171. #define SOH 1
  172. #define STX 2
  173. #define EOT 4
  174. #define ACK 6
  175. #define NAK 025
  176. #define CPMEOF 032
  177. #define WANTCRC 0103    /* send C not NAK to get crc not checksum */
  178. #define WANTG 0107    /* Send G not NAK to get nonstop batch xmsn */
  179. #define TIMEOUT (-2)
  180. #define RCDO (-3)
  181. #define GCOUNT (-4)
  182. #define RETRYMAX 10
  183.  
  184.  
  185. #define HOWMANY 2
  186. STATIC int Zmodem=0;        /* ZMODEM protocol requested by receiver */
  187. unsigned Baudrate=4800;        /* Default, set by first mode() call */
  188. STATIC unsigned Effbaud = 4800;
  189. STATIC unsigned Txwindow;    /* Control the size of the transmitted window */
  190. STATIC unsigned Txwspac;    /* Spacing between zcrcq requests */
  191. STATIC unsigned Txwcnt;    /* Counter used to space ack requests */
  192. STATIC long Lrxpos;        /* Receiver's last reported offset */
  193. STATIC int errors;
  194.  
  195. #ifdef vax11c
  196. #include "vrzsz.c"    /* most of the system dependent stuff here */
  197. #else
  198. #ifdef GENIE
  199. #include "genie.c"    /* most of the system dependent stuff here */
  200. #else
  201. #include "rbsb.c"    /* most of the system dependent stuff here */
  202. #ifdef XX
  203. #undef STAT
  204. #endif
  205. #endif
  206. #endif
  207.  
  208. #include "crctab.c"
  209.  
  210. STATIC int Filesleft;
  211. STATIC long Totalleft;
  212.  
  213. /*
  214.  * Attention string to be executed by receiver to interrupt streaming data
  215.  *  when an error is detected.  A pause (0336) may be needed before the
  216.  *  ^C (03) or after it.
  217.  */
  218. #ifdef READCHECK
  219. STATIC char Myattn[] = { 0 };
  220. #else
  221. #ifdef USG
  222. STATIC char Myattn[] = { 03, 0336, 0 };
  223. #else
  224. #ifndef GENIE
  225. STATIC char Myattn[] = { 0 };
  226. #endif
  227. #endif
  228. #endif
  229.  
  230. FILE *in;
  231.  
  232. #ifdef BADSEEK
  233. STATIC int Canseek = 0;    /* 1: Can seek 0: only rewind -1: neither (pipe) */
  234. #ifndef TXBSIZE
  235. #define TXBSIZE 16384        /* Must be power of two, < MAXINT */
  236. #endif
  237. #else
  238. STATIC int Canseek = 1;    /* 1: Can seek 0: only rewind -1: neither (pipe) */
  239. #endif
  240.  
  241. #ifdef TXBSIZE
  242. #define TXBMASK (TXBSIZE-1)
  243. STATIC char Txb[TXBSIZE];        /* Circular buffer for file reads */
  244. STATIC char *txbuf = Txb;        /* Pointer to current file segment */
  245. #else
  246. STATIC char txbuf[1024];
  247. #endif
  248. STATIC long vpos = 0;            /* Number of bytes read from file */
  249.  
  250. STATIC char Lastrx;
  251. STATIC char Crcflg;
  252. STATIC int Verbose=0;
  253. STATIC int Modem2=0;        /* XMODEM Protocol - don't send pathnames */
  254. STATIC int Restricted=0;    /* restricted; no /.. or ../ in filenames */
  255. STATIC int Quiet=0;        /* overrides logic that would otherwise
  256. set verbose */
  257. STATIC int Ascii=0;        /* Add CR's for brain damaged programs */
  258. STATIC int Fullname=0;        /* transmit full pathname */
  259. STATIC int Unlinkafter=0;    /* Unlink file after it is sent */
  260. STATIC int Dottoslash=0;    /* Change foo.bar.baz to foo/bar/baz */
  261. STATIC int firstsec;
  262. STATIC int errcnt=0;        /* number of files unreadable */
  263. STATIC int blklen=128;        /* length of transmitted records */
  264. STATIC int Optiong;        /* Let it rip no wait for sector ACK's */
  265. STATIC int Eofseen;        /* EOF seen on input set by zfilbuf */
  266. STATIC int BEofseen;        /* EOF seen on input set by fooseek */
  267. STATIC int Totsecs;        /* total number of sectors this file */
  268. STATIC int Filcnt=0;        /* count of number of files opened */
  269. STATIC int Lfseen=0;
  270. STATIC unsigned Rxbuflen = 16384;    /* Receiver's max buffer length */
  271. STATIC int Tframlen = 0;    /* Override for tx frame length */
  272. STATIC int blkopt=0;        /* Override value for zmodem blklen */
  273. STATIC int Rxflags = 0;
  274. STATIC long bytcnt;
  275. STATIC int Wantfcs32 = TRUE;    /* want to send 32 bit FCS */
  276. STATIC char Lzconv;    /* Local ZMODEM file conversion request */
  277. STATIC char Lzmanag;    /* Local ZMODEM file management request */
  278. STATIC int Lskipnocor;
  279. STATIC char Lztrans;
  280. STATIC int Command;        /* Send a command, then exit. */
  281. STATIC char *Cmdstr;        /* Pointer to the command string */
  282. STATIC int Cmdtries = 11;
  283. STATIC int Cmdack1;        /* Rx ACKs command, then do it */
  284. STATIC int Exitcode;
  285. STATIC int Test;        /* 1= Force receiver to send Attn, etc with qbf. */
  286.             /* 2= Character transparency test */
  287. STATIC char *qbf=
  288.  "The quick brown fox jumped over the lazy dog's back 1234567890\r\n";
  289. STATIC long Lastsync;        /* Last offset to which we got a ZRPOS */
  290. STATIC int Beenhereb4;        /* How many times we've been ZRPOS'd same place */
  291.  
  292. STATIC jmp_buf tohere;        /* For the interrupt on RX timeout */
  293. STATIC jmp_buf intrjmp;    /* For the interrupt on RX CAN */
  294.  
  295. #ifdef XARGSFILE
  296. char *
  297. mystrsave(s)
  298. char *s;
  299. {
  300.     register char *p;
  301.     char *malloc();
  302.  
  303.     if (p = malloc(strlen(s)+1) ) {
  304.         strcpy(p, s); return p;
  305.     }
  306.     fprintf(stderr, "No memory for mystrsave!\n");
  307.     exit(1);
  308. }
  309.  
  310. /* Remove (presumably) terminating CR and/or LF from string */
  311. uncrlf(s)
  312. register char *s;
  313. {
  314.     for ( ; *s; ++s)
  315.         switch (*s) {
  316.         case '\r':
  317.         case '\n':
  318.             *s = 0;  return;
  319.         }
  320. }
  321. #endif
  322.  
  323.  
  324. /* called by signal interrupt or terminate to clean things up */
  325. bibi(n)
  326. {
  327.     canit(); fflush(stdout); mode(0);
  328.     fprintf(stderr, "sz: caught signal %d; exiting\n", n);
  329. #ifndef GENIE
  330.     if (n == SIGQUIT)
  331.         abort();
  332. #endif
  333.     if (n == 99)
  334.         fprintf(stderr, "mode(2) in rbsb.c not implemented!!\n");
  335.     cucheck();
  336.     exit(128+n);
  337. }
  338. /* Called when ZMODEM gets an interrupt (^X) */
  339. onintr()
  340. {
  341.     signal(SIGINT, SIG_IGN);
  342.     longjmp(intrjmp, -1);
  343. }
  344.  
  345. STATIC int Zctlesc;    /* Encode control characters */
  346. STATIC int Nozmodem = 0;    /* If invoked as "sb" */
  347. STATIC char *Progname = "sz";
  348. STATIC int Zrwindow = 1400;    /* RX window size (controls garbage count) */
  349. #include "zm.c"
  350.  
  351. #include "zmr.c"
  352.  
  353. #ifdef XARGSFILE
  354. #define XARGSMAX 256
  355. char *xargv[XARGSMAX+1];
  356. #endif
  357.  
  358. main(argc, argv)
  359. char *argv[];
  360. {
  361.     register char *cp;
  362.     register npats;
  363.     int dm;
  364.     char **patts;
  365.     static char xXbuf[BUFSIZ];
  366.  
  367.     if ((cp = getenv("ZNULLS")) && *cp)
  368.         Znulls = atoi(cp);
  369.     if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh")))
  370.         Restricted=TRUE;
  371.     from_cu();
  372. #ifdef vax11c
  373.     chkinvok(PROGNAME);
  374. #else
  375.     chkinvok(argv[0]);
  376. #endif
  377.  
  378.     Rxtimeout = 600;
  379.     npats=0;
  380.     if (argc<2)
  381.         usage();
  382.     setbuf(stdout, xXbuf);        
  383.     while (--argc) {
  384.         cp = *++argv;
  385.         if (*cp++ == '-' && *cp) {
  386.             while ( *cp) {
  387.                 switch(*cp++) {
  388.                 case '\\':
  389.                      *cp = toupper(*cp);  continue;
  390.                 case '+':
  391.                     Lzmanag = ZMAPND; break;
  392. #ifdef CSTOPB
  393.                 case '2':
  394.                     Twostop = TRUE; break;
  395. #endif
  396.                 case 'a':
  397.                     Lzconv = ZCNL;
  398.                     Ascii = TRUE; break;
  399.                 case 'b':
  400.                     Lzconv = ZCBIN; break;
  401.                 case 'C':
  402.                     if (--argc < 1) {
  403.                         usage();
  404.                     }
  405.                     Cmdtries = atoi(*++argv);
  406.                     break;
  407.                 case 'i':
  408.                     Cmdack1 = ZCACK1;
  409.                     /* **** FALL THROUGH TO **** */
  410.                 case 'c':
  411.                     if (--argc != 1) {
  412.                         usage();
  413.                     }
  414.                     Command = TRUE;
  415.                     Cmdstr = *++argv;
  416.                     break;
  417.                 case 'd':
  418.                     ++Dottoslash;
  419.                     /* **** FALL THROUGH TO **** */
  420.                 case 'f':
  421.                     Fullname=TRUE; break;
  422.                 case 'e':
  423.                     Zctlesc = 1; break;
  424.                 case 'k':
  425.                     blklen=1024; break;
  426.                 case 'L':
  427.                     if (--argc < 1) {
  428.                         usage();
  429.                     }
  430.                     blkopt = atoi(*++argv);
  431.                     if (blkopt<24 || blkopt>1024)
  432.                         usage();
  433.                     break;
  434.                 case 'l':
  435.                     if (--argc < 1) {
  436.                         usage();
  437.                     }
  438.                     Tframlen = atoi(*++argv);
  439.                     if (Tframlen<32 || Tframlen>1024)
  440.                         usage();
  441.                     break;
  442.                 case 'N':
  443.                     Lzmanag = ZMNEWL;  break;
  444.                 case 'n':
  445.                     Lzmanag = ZMNEW;  break;
  446.                 case 'o':
  447.                     Wantfcs32 = FALSE; break;
  448.                 case 'p':
  449.                     Lzmanag = ZMPROT;  break;
  450.                 case 'r':
  451.                     if (Lzconv == ZCRESUM)
  452.                         Lzmanag = (Lzmanag &
  453. ZMMASK) | ZMCRC;
  454.                     Lzconv = ZCRESUM; break;
  455.                 case 'q':
  456.                     Quiet=TRUE; Verbose=0; break;
  457.                 case 't':
  458.                     if (--argc < 1) {
  459.                         usage();
  460.                     }
  461.                     Rxtimeout = atoi(*++argv);
  462.                     if (Rxtimeout<10 || Rxtimeout>1000)
  463.                         usage();
  464.                     break;
  465.                 case 'T':
  466.                     if (++Test > 1) {
  467.                         chartest(1); chartest(2);
  468.                         mode(0);  exit(0);
  469.                     }
  470.                     break;
  471. #ifndef vax11c
  472.                 case 'u':
  473.                     ++Unlinkafter; break;
  474. #endif
  475.                 case 'v':
  476.                     ++Verbose; break;
  477.                 case 'w':
  478.                     if (--argc < 1) {
  479.                         usage();
  480.                     }
  481.                     Txwindow = atoi(*++argv);
  482.                     if (Txwindow < 256)
  483.                         Txwindow = 256;
  484.                     Txwindow = (Txwindow/64) * 64;
  485.                     Txwspac = Txwindow/4;
  486.                     if (blkopt > Txwspac
  487.                      || (!blkopt && Txwspac < 1024))
  488.                         blkopt = Txwspac;
  489.                     break;
  490.                 case 'X':
  491.                     ++Modem2; break;
  492.                 case 'Y':
  493.                     Lskipnocor = TRUE;
  494.                     /* **** FALLL THROUGH TO **** */
  495.                 case 'y':
  496.                     Lzmanag = ZMCLOB; break;
  497.                 case 'Z':
  498.                 case 'z':
  499.                     Lztrans = ZTRLE;  break;
  500.                 default:
  501.                     usage();
  502.                 }
  503.             }
  504.         }
  505.         else if ( !npats && argc>0) {
  506.             if (argv[0][0]) {
  507.                 npats=argc;
  508.                 patts=argv;
  509.             }
  510.         }
  511.     }
  512.     if (npats < 1 && !Command && !Test) 
  513.         usage();
  514.     if (Verbose) {
  515.         if (freopen(LOGFILE, "a", stderr)==NULL) {
  516.             printf("Can't open log file %s\n",LOGFILE);
  517.             exit(0200);
  518.         }
  519.         setbuf(stderr, NULL);
  520.     }
  521.     if (Fromcu && !Quiet) {
  522.         if (Verbose == 0)
  523.             Verbose = 2;
  524.     }
  525.     vfile("%s %s for %s\n", Progname, VERSION, OS);
  526.  
  527. #ifdef XARGSFILE
  528.     vfile("npats=%d *patts=%s", npats, *patts);
  529.     if (npats == 1 && !strcmp(XARGSFILE, *patts)) {
  530.         in = fopen(XARGSFILE, "r");
  531.         if (!in) {
  532.             printf(stderr, "Can't open / control file!\n");
  533.             exit(2);
  534.         }
  535.         for (npats=0,argv=patts=xargv; npats<XARGSMAX; ++npats,++argv) {
  536.             if (fgets(txbuf, 1024, in) <= 0)
  537.                 break;
  538.             uncrlf(txbuf);
  539.             *argv = mystrsave(txbuf);
  540.         }
  541.         fclose(in);
  542.     }
  543. #endif
  544.  
  545.     mode(1);
  546.  
  547. #ifdef GENIE
  548.     signal(SIGINT, SIG_IGN);
  549. #else
  550.     if (signal(SIGINT, bibi) == SIG_IGN) {
  551.         signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);
  552.     } else {
  553.         signal(SIGINT, bibi); signal(SIGKILL, bibi);
  554.     }
  555. #endif
  556. #ifdef SIGQUIT
  557.     if ( !Fromcu)
  558.         signal(SIGQUIT, SIG_IGN);
  559. #endif
  560. #ifdef SIGTERM
  561.     signal(SIGTERM, bibi);
  562. #endif
  563.  
  564.     if ( !Modem2) {
  565.         if (!Nozmodem) {
  566.             printf("rz\r");  fflush(stdout);
  567.         }
  568.         countem(npats, patts);
  569.         if (!Nozmodem) {
  570.             stohdr(0L);
  571.             if (Command)
  572.                 Txhdr[ZF0] = ZCOMMAND;
  573.             zshhdr(4, ZRQINIT, Txhdr);
  574.         }
  575.     }
  576.     fflush(stdout);
  577.  
  578.     if (Command) {
  579.         if (getzrxinit()) {
  580.             Exitcode=0200; canit();
  581.         }
  582.         else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) {
  583.             Exitcode=0200; canit();
  584.         }
  585.     } else if (wcsend(npats, patts)==ERROR) {
  586.         Exitcode=0200;
  587.         canit();
  588.     }
  589.     fflush(stdout);
  590.     mode(0);
  591.     dm = ((errcnt != 0) | Exitcode);
  592.     if (dm) {
  593.         cucheck();  exit(dm);
  594.     }
  595.     exit(SS_NORMAL);
  596.     /*NOTREACHED*/
  597. }
  598.  
  599. wcsend(argc, argp)
  600. char *argp[];
  601. {
  602.     register n;
  603.  
  604.     Crcflg=FALSE;
  605.     firstsec=TRUE;
  606.     bytcnt = -1;
  607.     if (Nozmodem) {
  608.         printf("Start your YMODEM receive. ");  fflush(stdout);
  609.     }
  610.     for (n=0; n<argc; ++n) {
  611.         Totsecs = 0;
  612.         if (wcs(argp[n])==ERROR)
  613.             return ERROR;
  614.     }
  615.     Totsecs = 0;
  616.     if (Filcnt==0) {    /* bitch if we couldn't open ANY files */
  617.         if (!Nozmodem && !Modem2) {
  618.             Command = TRUE;
  619.             Cmdstr = "echo \"sz: Can't open any requested files\"";
  620.             if (getnak()) {
  621.                 Exitcode=0200; canit();
  622.             }
  623.             if (!Zmodem)
  624.                 canit();
  625.             else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) {
  626.                 Exitcode=0200; canit();
  627.             }
  628.             Exitcode = 1; return OK;
  629.         }
  630.         canit();
  631.         fprintf(stderr,"\r\nCan't open any requested files.\r\n");
  632.         return ERROR;
  633.     }
  634.     if (Zmodem)
  635.         saybibi();
  636.     else if ( !Modem2)
  637.         wctxpn("");
  638.     return OK;
  639. }
  640.  
  641. wcs(oname)
  642. char *oname;
  643. {
  644.     register c;
  645.     register char *p, *q;
  646. #ifdef STAT
  647.     struct stat f;
  648. #endif
  649.     char name[PATHLEN];
  650.  
  651.     strcpy(name, oname);
  652.  
  653. #ifdef XARGSFILE
  654.     /* Parse GEniename:REALname:length pathname syntax */
  655.     Thisflen = -1;
  656.     for (p = oname; *p; ++p) {
  657.         if (*p == ':') {
  658.             *p++ = 0;
  659.             q = p;
  660.             for (++p; *p; ++p) {
  661.                 if (*p == ':') {
  662.                     *p++ = 0;
  663.                     Thisflen = atol(p);
  664.                     break;
  665.                 }
  666.             }
  667.             strcpy(name, q);
  668.             break;
  669.         }
  670.     }
  671. #endif
  672.  
  673. #ifdef GENIE
  674.     _describe(oname,&fdes);        /* An undocumented goodie */
  675.     if (fdes.type_file == 1) {    /* Fortran Sequential Binary */
  676.         Binfile = 1;
  677.         in = fopen(oname,"rB");
  678.     }
  679.     else if (fdes.type_file == 0)  { /* Ascii */
  680.         Binfile = 0;
  681.         in = fopen(oname,"r");
  682.     }
  683.     else {                /* not a SL filetype */
  684.         fprintf(stderr, "\nUnknown file type %d\n",fdes.type_file);
  685.         ++errcnt;
  686.         return OK;        /* pass over it, there may be others */
  687.     }
  688. #else
  689.     if (Restricted) {
  690.         /* restrict pathnames to current tree or uucppublic */
  691.         if ( substr(name, "../")
  692.          || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) {
  693.             canit();
  694.             fprintf(stderr,"\r\nsz:\tSecurity Violation\r\n");
  695.             return ERROR;
  696.         }
  697.     }
  698.  
  699.     in=fopen(oname, ROPMODE);
  700. #endif
  701.  
  702.     if (in==NULL) {
  703.         ++errcnt;
  704.         return OK;    /* pass over it, there may be others */
  705.     }
  706.     BEofseen = Eofseen = 0;  vpos = 0;
  707.  
  708. #ifdef STAT
  709.     /* Check for directory or block special files */
  710.     fstat(fileno(in), &f);
  711.     c = f.st_mode & S_IFMT;
  712.     if (c == S_IFDIR || c == S_IFBLK) {
  713.         fclose(in);
  714.         return OK;
  715.     }
  716. #endif
  717.  
  718.     ++Filcnt;
  719.     switch (wctxpn(name)) {
  720.     case ERROR:
  721.         return ERROR;
  722.     case ZSKIP:
  723.         return OK;
  724.     }
  725. #ifdef STAT
  726.     if (!Zmodem && wctx(f.st_size)==ERROR)
  727.         return ERROR;
  728. #else
  729.     if (!Zmodem && wctx(1000000000L)==ERROR)
  730.         return ERROR;
  731. #endif
  732.  
  733. #ifndef vax11c
  734. #ifndef GENIE
  735.     if (Unlinkafter)
  736.         unlink(oname);
  737. #endif
  738. #endif
  739.  
  740.     return 0;
  741. }
  742.  
  743. /*
  744.  * generate and transmit pathname block consisting of
  745.  *  pathname (null terminated),
  746.  *  file length, mode time and file mode in octal
  747.  *  as provided by the Unix fstat call.
  748.  *  N.B.: modifies the passed name, may extend it!
  749.  */
  750. wctxpn(name)
  751. char *name;
  752. {
  753.     register char *p, *q;
  754.     char name2[PATHLEN];
  755. #ifdef STAT
  756.     struct stat f;
  757. #endif
  758.  
  759.     if (Modem2) {
  760. #ifdef STAT
  761.         if (*name && fstat(fileno(in), &f)!= -1) {
  762.             fprintf(stderr, "Sending %s, %ld XMODEM blocks. ",
  763.               name, (127+f.st_size)>>7);
  764.         }
  765. #endif
  766.         fprintf(stderr, "Give your local XMODEM receive command now.\r\n");
  767.         fflush(stderr);
  768.         return OK;
  769.     }
  770.     zperr("Awaiting pathname nak for %s", *name?name:"<END>");
  771.     if ( !Zmodem)
  772.         if (getnak())
  773.             return ERROR;
  774.  
  775.     q = (char *) 0;
  776.     if (Dottoslash) {        /* change . to . */
  777.         for (p=name; *p; ++p) {
  778.             if (*p == '/')
  779.                 q = p;
  780.             else if (*p == '.')
  781.                 *(q=p) = '/';
  782.         }
  783.         if (q && strlen(++q) > 8) {    /* If name>8 chars */
  784.             q += 8;            /*   make it .ext */
  785.             strcpy(name2, q);    /* save excess of name */
  786.             *q = '.';
  787.             strcpy(++q, name2);    /* add it back */
  788.         }
  789.     }
  790.  
  791.     for (p=name, q=txbuf ; *p; )
  792.         if ((*q++ = *p++) == '/' && !Fullname)
  793.             q = txbuf;
  794.     *q++ = 0;
  795.     p=q;
  796.     while (q < (txbuf + 1024))
  797.         *q++ = 0;
  798.     if (*name) {
  799. #ifdef XX
  800.         if (Thisflen >= 0) {
  801.             sprintf(p, "%u 0 0 0 %d %ld",
  802.               Thisflen, Filesleft, Totalleft);
  803.             Totalleft -= Thisflen;
  804.         }
  805. #endif
  806. #ifdef GENIE
  807.         else
  808.             sprintf(p, "%d", fdes.current_file_size * 1260);
  809.         vfile("%s open Binfile=%d size=%ld", name, Binfile,
  810.           fdes.current_file_size * 1260);
  811. #endif
  812.  
  813. #ifdef STAT
  814. #ifndef XX
  815.         if (fstat(fileno(in), &f)!= -1)
  816.             sprintf(p, "%lu %lo %o 0 %d %ld", f.st_size, f.st_mtime,
  817.               f.st_mode, Filesleft, Totalleft);
  818.         Totalleft -= f.st_size;
  819. #endif
  820. #endif
  821.  
  822.     }
  823.     if (--Filesleft <= 0)
  824.         Totalleft = 0;
  825.     if (Totalleft < 0)
  826.         Totalleft = 0;
  827.  
  828. #ifdef STAT
  829.     /* force 1k blocks if name won't fit in 128 byte block */
  830.     if (txbuf[125])
  831.         blklen=1024;
  832.     else {        /* A little goodie for IMP/KMD */
  833.         txbuf[127] = (f.st_size + 127) >>7;
  834.         txbuf[126] = (f.st_size + 127) >>15;
  835.     }
  836. #endif
  837.     if (Zmodem)
  838.         return zsendfile(txbuf, 1+strlen(p)+(p-txbuf));
  839.     if (wcputsec(txbuf, 0, 128)==ERROR)
  840.         return ERROR;
  841.     return OK;
  842. }
  843.  
  844. getnak()
  845. {
  846.     register firstch;
  847.  
  848.     Lastrx = 0;
  849.     for (;;) {
  850.         switch (firstch = readline(800)) {
  851.         case ZPAD:
  852.             if (getzrxinit())
  853.                 return ERROR;
  854.             Ascii = 0;    /* Receiver does the conversion */
  855.             return FALSE;
  856.         case TIMEOUT:
  857.             zperr("Timeout on pathname");
  858.             return TRUE;
  859.         case WANTG:
  860. #ifdef MODE2OK
  861.             mode(2);    /* Set cbreak, XON/XOFF, etc. */
  862. #endif
  863.             Optiong = TRUE;
  864.             blklen=1024;
  865.         case WANTCRC:
  866.             Crcflg = TRUE;
  867.         case NAK:
  868.             return FALSE;
  869.         case CAN:
  870.             if ((firstch = readline(20)) == CAN && Lastrx == CAN)
  871.                 return TRUE;
  872.         default:
  873.             break;
  874.         }
  875.         Lastrx = firstch;
  876.     }
  877. }
  878.  
  879.  
  880. wctx(flen)
  881. long flen;
  882. {
  883.     register int thisblklen;
  884.     register int sectnum, attempts, firstch;
  885.     long charssent;
  886.  
  887.     charssent = 0;  firstsec=TRUE;  thisblklen = blklen;
  888.     vfile("wctx:file length=%ld", flen);
  889.  
  890.     while ((firstch=readline(Rxtimeout))!=NAK && firstch != WANTCRC
  891.       && firstch != WANTG && firstch!=TIMEOUT && firstch!=CAN)
  892.         ;
  893.     if (firstch==CAN) {
  894.         zperr("Receiver CANcelled");
  895.         return ERROR;
  896.     }
  897.     if (firstch==WANTCRC)
  898.         Crcflg=TRUE;
  899.     if (firstch==WANTG)
  900.         Crcflg=TRUE;
  901.     sectnum=0;
  902.     for (;;) {
  903.         if (flen <= (charssent + 896L))
  904.             thisblklen = 128;
  905.         if ( !filbuf(txbuf, thisblklen))
  906.             break;
  907.         if (wcputsec(txbuf, ++sectnum, thisblklen)==ERROR)
  908.             return ERROR;
  909.         charssent += thisblklen;
  910.     }
  911.     fclose(in);
  912.     attempts=0;
  913.     do {
  914.         purgeline();
  915.         sendline(EOT);
  916.         flushmo();
  917.         ++attempts;
  918.     }
  919.         while ((firstch=(readline(Rxtimeout)) != ACK) &&
  920. attempts < RETRYMAX);
  921.     if (attempts == RETRYMAX) {
  922.         zperr("No ACK on EOT");
  923.         return ERROR;
  924.     }
  925.     else
  926.         return OK;
  927. }
  928.  
  929. wcputsec(buf, sectnum, cseclen)
  930. char *buf;
  931. int sectnum;
  932. int cseclen;    /* data length of this sector to send */
  933. {
  934.     register checksum, wcj;
  935.     register char *cp;
  936.     unsigned oldcrc;
  937.     int firstch;
  938.     int attempts;
  939.  
  940.     firstch=0;    /* part of logic to detect CAN CAN */
  941.  
  942.     if (Verbose>2)
  943.         fprintf(stderr, "Sector %3d %2dk\n", Totsecs, Totsecs/8 );
  944.     else if (Verbose>1)
  945.         fprintf(stderr, "\rSector %3d %2dk ", Totsecs, Totsecs/8 );
  946.     for (attempts=0; attempts <= RETRYMAX; attempts++) {
  947.         Lastrx= firstch;
  948.         sendline(cseclen==1024?STX:SOH);
  949.         sendline(sectnum);
  950.         sendline(-sectnum -1);
  951.         oldcrc=checksum=0;
  952.         for (wcj=cseclen,cp=buf; --wcj>=0; ) {
  953.             sendline(*cp);
  954.             oldcrc=updcrc((0377& *cp), oldcrc);
  955.             checksum += *cp++;
  956.         }
  957.         if (Crcflg) {
  958.             oldcrc=updcrc(0,updcrc(0,oldcrc));
  959.             sendline((int)oldcrc>>8);
  960.             sendline((int)oldcrc);
  961.         }
  962.         else
  963.             sendline(checksum);
  964.         flushmo();
  965.  
  966.         if (Optiong) {
  967.             firstsec = FALSE; return OK;
  968.         }
  969.         firstch = readline(Rxtimeout);
  970. gotnak:
  971.         switch (firstch) {
  972.         case CAN:
  973.             if(Lastrx == CAN) {
  974. cancan:
  975.                 zperr("Cancelled");  return ERROR;
  976.             }
  977.             break;
  978.         case TIMEOUT:
  979.             zperr("Timeout on sector ACK"); continue;
  980.         case WANTCRC:
  981.             if (firstsec)
  982.                 Crcflg = TRUE;
  983.         case NAK:
  984.             zperr("NAK on sector"); continue;
  985.         case ACK: 
  986.             firstsec=FALSE;
  987.             Totsecs += (cseclen>>7);
  988.             return OK;
  989.         case ERROR:
  990.             zperr("Got burst for sector ACK"); break;
  991.         default:
  992.             zperr("Got %02x for sector ACK", firstch); break;
  993.         }
  994.         for (;;) {
  995.             Lastrx = firstch;
  996.             if ((firstch = readline(Rxtimeout)) == TIMEOUT)
  997.                 break;
  998.             if (firstch == NAK || firstch == WANTCRC)
  999.                 goto gotnak;
  1000.             if (firstch == CAN && Lastrx == CAN)
  1001.                 goto cancan;
  1002.         }
  1003.     }
  1004.     zperr("Retry Count Exceeded");
  1005.     return ERROR;
  1006. }
  1007.  
  1008. /* fill buf with count chars padding with ^Z for CPM */
  1009. filbuf(buf, count)
  1010. register char *buf;
  1011. {
  1012.     register c, m;
  1013.  
  1014.     if ( !Ascii) {
  1015.         m = read(fileno(in), buf, count);
  1016.         if (m <= 0)
  1017.             return 0;
  1018.         while (m < count)
  1019.             buf[m++] = 032;
  1020.         return count;
  1021.     }
  1022.     m=count;
  1023.     if (Lfseen) {
  1024.         *buf++ = 012; --m; Lfseen = 0;
  1025.     }
  1026.     while ((c=getc(in))!=EOF) {
  1027.         if (c == 012) {
  1028.             *buf++ = 015;
  1029.             if (--m == 0) {
  1030.                 Lfseen = TRUE; break;
  1031.             }
  1032.         }
  1033.         *buf++ =c;
  1034.         if (--m == 0)
  1035.             break;
  1036.     }
  1037.     if (m==count)
  1038.         return 0;
  1039.     else
  1040.         while (--m>=0)
  1041.             *buf++ = CPMEOF;
  1042.     return count;
  1043. }
  1044.  
  1045. /* Fill buffer with blklen chars */
  1046. zfilbuf()
  1047. {
  1048.     int n;
  1049.  
  1050. #ifdef TXBSIZE
  1051.     vfile("zfilbuf: bytcnt =%lu vpos=%lu blklen=%d", bytcnt, vpos, blklen);
  1052.     /* We assume request is within buffer, or just beyond */
  1053.     txbuf = Txb + (bytcnt & TXBMASK);
  1054.     if (vpos <= bytcnt) {
  1055. #ifdef GENIE
  1056.         if (Binfile) {
  1057.             long l, m;  char *p;
  1058.  
  1059.             for (p=txbuf, n=0, l=blklen;  l;  l -= 128, p+= 128) {
  1060.                 n += m = fgetb(p, 128, in);
  1061.                 if (m == 0)
  1062.                     break;
  1063.             }
  1064.         } else
  1065. #endif
  1066.         n = fread(txbuf, 1, blklen, in);
  1067.  
  1068.         vpos += n;
  1069.         if (n < blklen)
  1070.             Eofseen = 1;
  1071.         vfile("zfilbuf: n=%d vpos=%lu Eofseen=%d", n, vpos, Eofseen);
  1072.         return n;
  1073.     }
  1074.     if (vpos >= (bytcnt+blklen))
  1075.         return blklen;
  1076.     /* May be a short block if crash recovery etc. */
  1077.     Eofseen = BEofseen;
  1078.     return (vpos - bytcnt);
  1079. #else
  1080.     n = fread(txbuf, 1, blklen, in);
  1081.     if (n < blklen)
  1082.         Eofseen = 1;
  1083.     return n;
  1084. #endif
  1085. }
  1086.  
  1087. #ifdef TXBSIZE
  1088. /* Replacement for brain damaged fseek function.  Returns 0==success */
  1089. fooseek(fptr, pos, whence)
  1090. FILE *fptr;
  1091. long pos;
  1092. {
  1093.     long m, n;
  1094. #ifdef GENIE
  1095.     long l, k;  char *p;
  1096. #endif
  1097.  
  1098.     vfile("fooseek: pos =%lu vpos=%lu Canseek=%d", pos, vpos, Canseek);
  1099.     /* Seek offset < current buffer */
  1100.     if (pos < (vpos -TXBSIZE +1024)) {
  1101.         BEofseen = 0;
  1102.         if (Canseek > 0) {
  1103.             vpos = pos & ~TXBMASK;
  1104.             if (vpos >= pos)
  1105.                 vpos -= TXBSIZE;
  1106.             if (fseek(fptr, vpos, 0))
  1107.                 return 1;
  1108.         }
  1109.         else if (Canseek == 0) {
  1110. #ifdef GENIE
  1111.             if (Binfile) {
  1112.                 if (fseekb(fptr, vpos = 0L, 0))
  1113.                     return 1;
  1114.                 } else
  1115. #endif
  1116.             if (fseek(fptr, vpos = 0L, 0))
  1117.                 return 1;
  1118.         } else
  1119.             return 1;
  1120.         while (vpos < pos) {
  1121. #ifdef GENIE
  1122.             if (Binfile) {
  1123.                 for (p=Txb,n=0,l=TXBSIZE; l; l -= 128,p+= 128) {
  1124.                     n += (k = fgetb(p, 128, fptr));
  1125.                     vfile("bsk1: l=%d k=%d", l, k);
  1126.                     if (k == 0)
  1127.                         break;
  1128.                 }
  1129.             } else
  1130. #endif
  1131.             n = fread(Txb, 1, TXBSIZE, fptr);
  1132.             vpos += n;
  1133.             vfile("n=%d vpos=%ld", n, vpos);
  1134.             if (n < TXBSIZE) {
  1135.                 BEofseen = 1;
  1136.                 break;
  1137.             }
  1138.         }
  1139.         vfile("vpos=%ld", vpos);
  1140.         return 0;
  1141.     }
  1142.     /* Seek offset > current buffer (Crash Recovery, etc.) */
  1143.     if (pos > vpos) {
  1144.         if (Canseek)
  1145.             if (fseek(fptr, vpos = (pos & ~TXBMASK), 0))
  1146.                 return 1;
  1147.         while (vpos <= pos) {
  1148.             txbuf = Txb + (vpos & TXBMASK);
  1149.             m = TXBSIZE - (vpos & TXBMASK);
  1150.             vfile("m=%ld vpos=%ld", m,vpos);
  1151. #ifdef GENIE
  1152.             if (Binfile) {
  1153.                 for (p=txbuf,n=0,l=m; l; l -= 128,p+= 128) {
  1154.                     n += (k = fgetb(p, 128, fptr));
  1155.                     vfile("bsk2: l=%d k=%d n=%d", l, k, n);
  1156.                     if (k == 0)
  1157.                         break;
  1158.                 }
  1159.             } else
  1160. #endif
  1161.                 n = fread(txbuf, 1, m, fptr);
  1162.             vfile("n=%ld vpos=%ld", n,vpos);
  1163.             vpos += n;
  1164.             vfile("bo=%d m=%ld vpos=%ld", txbuf-Txb,m,vpos);
  1165.             if (n < m) {
  1166.                 BEofseen = 1;
  1167.                 break;
  1168.             }
  1169.         }
  1170.         return 0;
  1171.     }
  1172.     /* Seek offset is within current buffer */
  1173.     vfile("within buffer: vpos=%ld", vpos);
  1174.     return 0;
  1175. }
  1176. #define fseek fooseek
  1177. #endif
  1178.  
  1179.  
  1180. /* VARARGS1 */
  1181. vfile(f, a, b, c, d)
  1182. register char *f;
  1183. {
  1184.     if (Verbose > 2) {
  1185.         fprintf(stderr, f, a, b, c, d);
  1186.         fprintf(stderr, "\n");
  1187.     }
  1188. }
  1189.  
  1190.  
  1191. alrm()
  1192. {
  1193.     longjmp(tohere, -1);
  1194. }
  1195.  
  1196.  
  1197. #ifndef GENIE
  1198. #ifndef vax11c
  1199. /*
  1200.  * readline(timeout) reads character(s) from file descriptor 0
  1201.  * timeout is in tenths of seconds
  1202.  */
  1203. readline(timeout)
  1204. {
  1205.     register int c;
  1206.     static char byt[1];
  1207.  
  1208.     fflush(stdout);
  1209.     if (setjmp(tohere)) {
  1210.         zperr("TIMEOUT");
  1211.         return TIMEOUT;
  1212.     }
  1213.     c = timeout/10;
  1214.     if (c<2)
  1215.         c=2;
  1216.     if (Verbose>5) {
  1217.         fprintf(stderr, "Timeout=%d Calling alarm(%d) ", timeout, c);
  1218.     }
  1219.     signal(SIGALRM, alrm); alarm(c);
  1220.     c=read(0, byt, 1);
  1221.     alarm(0);
  1222.     if (Verbose>5)
  1223.         fprintf(stderr, "ret %x\n", byt[0]);
  1224.     if (c<1)
  1225.         return TIMEOUT;
  1226.     return (byt[0]&0377);
  1227. }
  1228.  
  1229. flushmo()
  1230. {
  1231.     fflush(stdout);
  1232. }
  1233.  
  1234.  
  1235. purgeline()
  1236. {
  1237. #ifdef USG
  1238.     ioctl(0, TCFLSH, 0);
  1239. #else
  1240.     lseek(0, 0L, 2);
  1241. #endif
  1242. }
  1243. #endif
  1244. #endif
  1245.  
  1246. /* send cancel string to get the other end to shut up */
  1247. canit()
  1248. {
  1249.     static char canistr[] = {
  1250.      24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
  1251.     };
  1252.  
  1253. #ifdef vax11c
  1254.     raw_wbuf(strlen(canistr), canistr);
  1255.     purgeline();
  1256. #else
  1257.     printf(canistr);
  1258.     fflush(stdout);
  1259. #endif
  1260. }
  1261.  
  1262.  
  1263. /*
  1264.  * Log an error
  1265.  */
  1266. /*VARARGS1*/
  1267. zperr(s,p,u)
  1268. char *s, *p, *u;
  1269. {
  1270.     if (Verbose <= 0)
  1271.         return;
  1272.     fprintf(stderr, "Retry %d: ", errors);
  1273.     fprintf(stderr, s, p, u);
  1274.     fprintf(stderr, "\n");
  1275. }
  1276.  
  1277. /*
  1278.  * substr(string, token) searches for token in string s
  1279.  * returns pointer to token within string if found, NULL otherwise
  1280.  */
  1281. char *
  1282. substr(s, t)
  1283. register char *s,*t;
  1284. {
  1285.     register char *ss,*tt;
  1286.     /* search for first char of token */
  1287.     for (ss=s; *s; s++)
  1288.         if (*s == *t)
  1289.             /* compare token with substring */
  1290.             for (ss=s,tt=t; ;) {
  1291.                 if (*tt == 0)
  1292.                     return s;
  1293.                 if (*ss++ != *tt++)
  1294.                     break;
  1295.             }
  1296.     return NULL;
  1297. }
  1298.  
  1299. char *babble[] = {
  1300. #ifdef vax11c
  1301.     "Send file(s) with ZMODEM/YMODEM/XMODEM Protocol",
  1302.     "    (Y) = Option applies to YMODEM only",
  1303.     "    (Z) = Option applies to ZMODEM only",
  1304.     "Usage:    sz [-2+abdefkLlNnquvwYy] [-] file ...",
  1305.     "    sz [-2Ceqv] -c COMMAND",
  1306.     "    \\ Force next option letter to upper case",
  1307.     "    sb [-2adfkquv] [-] file ...",
  1308.     "    sx [-2akquv] [-] file",
  1309. #endif
  1310. #ifndef vax11c
  1311.     "Send file(s) with ZMODEM/YMODEM/XMODEM Protocol",
  1312.     "    (Y) = Option applies to YMODEM only",
  1313.     "    (Z) = Option applies to ZMODEM only",
  1314.     "Usage:    sz [-2+abdefkLlNnquvwYy] [-] file ...",
  1315.     "    sz [-2Ceqv] -c COMMAND",
  1316.     "    sb [-2adfkquv] [-] file ...",
  1317.     "    sx [-2akquv] [-] file",
  1318. #endif
  1319. #ifdef CSTOPB
  1320.     "    2   Use 2 stop bits",
  1321. #endif
  1322.     "    +   Append to existing destination file (Z)",
  1323.     "    a   (ASCII) change NL to CR/LF",
  1324.     "    b   Binary file transfer override",
  1325.     "    c   send COMMAND (Z)",
  1326. #ifndef vax11c
  1327.     "    d   Change '.' to '/' in pathnames (Y/Z)",
  1328. #endif
  1329.     "    e   Escape all control characters (Z)",
  1330.     "    f   send Full pathname (Y/Z)",
  1331.     "    i   send COMMAND, ack Immediately (Z)",
  1332.     "    k   Send 1024 byte packets (Y)",
  1333.     "    L N Limit subpacket length to N bytes (Z)",
  1334.     "    l N Limit frame length to N bytes (l>=L) (Z)",
  1335.     "    n   send file only if source newer (Z)",
  1336.     "    N   send file only if source newer or longer (Z)",
  1337.     "    o   Use 16 bit CRC instead of 32 bit CRC (Z)",
  1338.     "    p   Protect existing destination file (Z)",
  1339.     "    r   Resume/Recover interrupted file transfer (Z)",
  1340.     "    q   Quiet (no progress reports)",
  1341. #ifndef vax11c
  1342.     "    u   Unlink (remove) file after transmission",
  1343. #endif
  1344.     "    v   Verbose - provide debugging information",
  1345.     "    w N restrict Window to N bytes (Z)",
  1346.     "    Y   Yes, overwrite existing file, skip if not present at rx (Z)",
  1347.     "    y   Yes, overwrite existing file (Z)",
  1348.     "    Z   Activate ZMODEM compression(Z)",
  1349.     ""
  1350. };
  1351.  
  1352. usage()
  1353. {
  1354.     char **pp;
  1355.  
  1356.     for (pp=babble; **pp; ++pp)
  1357.         fprintf(stderr, "%s\n", *pp);
  1358.     fprintf(stderr, "%s for %s by Chuck Forsberg, Omen Technology INC\n",
  1359.      VERSION, OS);
  1360.     fprintf(stderr, "\t\t\042The High Reliability Software\042\n");
  1361.     cucheck();
  1362.     exit(SS_NORMAL);
  1363. }
  1364.  
  1365. /*
  1366.  * Get the receiver's init parameters
  1367.  */
  1368. getzrxinit()
  1369. {
  1370.     register n;
  1371. #ifdef STAT
  1372.     struct stat f;
  1373. #endif
  1374.  
  1375.     for (n=10; --n>=0; ) {
  1376.         
  1377.         switch (zgethdr(Rxhdr, 1)) {
  1378.         case ZCHALLENGE:    /* Echo receiver's challenge numbr */
  1379.             stohdr(Rxpos);
  1380.             zshhdr(4, ZACK, Txhdr);
  1381.             continue;
  1382.         case ZCOMMAND:        /* They didn't see out ZRQINIT */
  1383.             stohdr(0L);
  1384.             zshhdr(4, ZRQINIT, Txhdr);
  1385.             continue;
  1386.         case ZRINIT:
  1387.             Rxflags = 0377 & Rxhdr[ZF0];
  1388.             Usevhdrs = Rxhdr[ZF1] & CANVHDR;
  1389.             Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
  1390.             Zctlesc |= Rxflags & TESCCTL;
  1391.             Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8);
  1392.             if ( !(Rxflags & CANFDX))
  1393.                 Txwindow = 0;
  1394.             vfile("Rxbuflen=%d Tframlen=%d", Rxbuflen, Tframlen);
  1395.             if ( !Fromcu)
  1396.                 signal(SIGINT, SIG_IGN);
  1397. #ifdef MODE2OK
  1398.             mode(2);    /* Set cbreak, XON/XOFF, etc. */
  1399. #endif
  1400.  
  1401. #ifndef READCHECK
  1402. #ifndef USG
  1403. #ifndef GENIE
  1404.             /* Use 1024 byte frames if no sample/interrupt */
  1405.             if (Rxbuflen < 32 || Rxbuflen > 1024) {
  1406.                 Rxbuflen = 1024;
  1407.                 vfile("Rxbuflen=%d", Rxbuflen);
  1408.             }
  1409. #endif
  1410. #endif
  1411. #endif
  1412.  
  1413.             /* Override to force shorter frame length */
  1414.             if (Rxbuflen && (Rxbuflen>Tframlen) && (Tframlen>=32))
  1415.                 Rxbuflen = Tframlen;
  1416.             if ( !Rxbuflen && (Tframlen>=32) && (Tframlen<=1024))
  1417.                 Rxbuflen = Tframlen;
  1418.             vfile("Rxbuflen=%d", Rxbuflen);
  1419.  
  1420. #ifndef GENIE
  1421. #ifndef vax11c
  1422. #ifdef STAT
  1423.             /* If using a pipe for testing set lower buf len */
  1424.             fstat(0, &f);
  1425.             if ((f.st_mode & S_IFMT) != S_IFCHR) {
  1426.                 Rxbuflen = 1024;
  1427.             }
  1428. #endif
  1429. #endif
  1430. #endif
  1431.  
  1432. #ifdef BADSEEK
  1433. #ifdef GENIE
  1434.             if (Txwindow == 0) {
  1435.                 Txwspac = (Txwindow = 4096)/4;
  1436.             }
  1437. #else
  1438.             if (Txwindow == 0)
  1439.                 Txwindow = TXBSIZE - 1024;
  1440.             Txwspac = TXBSIZE/4;
  1441. #endif
  1442.             Canseek = 0;
  1443. #endif
  1444.  
  1445.             /*
  1446.              * If input is not a regular file, force ACK's to
  1447.              *  prevent running beyond the buffer limits
  1448.              */
  1449. #ifdef STAT
  1450.             if ( !Command) {
  1451.                 fstat(fileno(in), &f);
  1452.                 if ((f.st_mode & S_IFMT) != S_IFREG) {
  1453.                     Canseek = -1;
  1454. #ifdef TXBSIZE
  1455.                     Txwindow = TXBSIZE - 1024;
  1456.                     Txwspac = TXBSIZE/4;
  1457. #else
  1458.                     return ERROR;
  1459. #endif
  1460.                 }
  1461.             }
  1462. #endif
  1463.  
  1464.             /* Set initial subpacket length */
  1465.             if (blklen < 1024) {    /* Command line override? */
  1466.                 if (Effbaud > 300)
  1467.                     blklen = 256;
  1468.                 if (Effbaud > 1200)
  1469.                     blklen = 512;
  1470.                 if (Effbaud > 2400)
  1471.                     blklen = 1024;
  1472.             }
  1473.             if (Rxbuflen && blklen>Rxbuflen)
  1474.                 blklen = Rxbuflen;
  1475.             if (blkopt && blklen > blkopt)
  1476.                 blklen = blkopt;
  1477. #ifdef GENIE
  1478.             blklen /= 128;  blklen *= 128;
  1479.             if (blklen < 128)
  1480.                 blklen = 128;
  1481. #endif
  1482.             vfile("Rxbuflen=%d blklen=%d", Rxbuflen, blklen);
  1483.             vfile("Txwindow = %u Txwspac = %d", Txwindow, Txwspac);
  1484.  
  1485.  
  1486.             if (Lztrans == ZTRLE && (Rxflags & CANRLE))
  1487.                 Txfcs32 = 2;
  1488.             else
  1489.                 Lztrans = 0;
  1490.  
  1491.             return (sendzsinit());
  1492.         case ZCAN:
  1493.         case TIMEOUT:
  1494.             return ERROR;
  1495.         case ZRQINIT:
  1496.             if (Rxhdr[ZF0] == ZCOMMAND)
  1497.                 continue;
  1498.         default:
  1499.             zshhdr(4, ZNAK, Txhdr);
  1500.             continue;
  1501.         }
  1502.     }
  1503.     return ERROR;
  1504. }
  1505.  
  1506. /* Send send-init information */
  1507. sendzsinit()
  1508. {
  1509.     register c;
  1510.  
  1511.     if (Myattn[0] == '\0' && (!Zctlesc || (Rxflags & TESCCTL)))
  1512.         return OK;
  1513.     errors = 0;
  1514.     for (;;) {
  1515.         stohdr(0L);
  1516. #ifdef ALTCANOFF
  1517.         Txhdr[ALTCOFF] = ALTCANOFF;
  1518. #endif
  1519.         if (Zctlesc) {
  1520.             Txhdr[ZF0] |= TESCCTL; zshhdr(4, ZSINIT, Txhdr);
  1521.         }
  1522.         else
  1523.             zsbhdr(4, ZSINIT, Txhdr);
  1524.         zsdata(Myattn, ZATTNLEN, ZCRCW);
  1525.         c = zgethdr(Rxhdr, 1);
  1526.         switch (c) {
  1527.         case ZCAN:
  1528.             return ERROR;
  1529.         case ZACK:
  1530.             return OK;
  1531.         default:
  1532.             if (++errors > 19)
  1533.                 return ERROR;
  1534.             continue;
  1535.         }
  1536.     }
  1537. }
  1538.  
  1539. /* Send file name and related info */
  1540. zsendfile(buf, blen)
  1541. char *buf;
  1542. {
  1543.     register c;
  1544.     register UNSL long crc;
  1545.     long lastcrcrq = -1;
  1546.     char *p;
  1547.  
  1548.     for (;;) {
  1549.         Txhdr[ZF0] = Lzconv;    /* file conversion request */
  1550.         Txhdr[ZF1] = Lzmanag;    /* file management request */
  1551.         if (Lskipnocor)
  1552.             Txhdr[ZF1] |= ZMSKNOLOC;
  1553.         Txhdr[ZF2] = Lztrans;    /* file transport request */
  1554.         Txhdr[ZF3] = 0;
  1555.         zsbhdr(4, ZFILE, Txhdr);
  1556.         zsdata(buf, blen, ZCRCW);
  1557. again:
  1558.         c = zgethdr(Rxhdr, 1);
  1559.         switch (c) {
  1560.         case ZRINIT:
  1561.             while ((c = readline(50)) > 0)
  1562.                 if (c == ZPAD) {
  1563.                     goto again;
  1564.                 }
  1565.             /* **** FALL THRU TO **** */
  1566.         default:
  1567.             continue;
  1568.         case ZCAN:
  1569.         case TIMEOUT:
  1570.         case ZABORT:
  1571.         case ZFIN:
  1572.             return ERROR;
  1573.         case ZCRC:
  1574.             if (Rxpos != lastcrcrq) {
  1575.                 lastcrcrq = Rxpos;
  1576.                 crc = 0xFFFFFFFFL;
  1577.                 if (Canseek >= 0) {
  1578.                     fseek(in, 0L, 0);
  1579.                     while (((c = getc(in)) != EOF)
  1580. && --lastcrcrq)
  1581.                         crc = UPDC32(c, crc);
  1582.                     crc = ~crc;
  1583.                     clearerr(in);    /* Clear possible EOF */
  1584.                     lastcrcrq = Rxpos;
  1585.                 }
  1586.             }
  1587.             stohdr(crc);
  1588.             zsbhdr(4, ZCRC, Txhdr);
  1589.             goto again;
  1590.         case ZSKIP:
  1591.             fclose(in); return c;
  1592.         case ZRPOS:
  1593.             /*
  1594.              * Suppress zcrcw request otherwise triggered by
  1595.              * lastyunc==bytcnt
  1596.              */
  1597. #ifdef GENIE
  1598.             /*
  1599.              *  Special case - turn on RLE if not archive, etc.
  1600.              *   otherwise turn off RLE unless cmd line specified
  1601.              */
  1602.             if (Rxflags & CANRLE) {        /* RX can do it */
  1603.                 bytcnt = 0;
  1604.                 zfilbuf();
  1605.                 vfile("txbuf012: %x %x %x", txbuf[0], txbuf[1],
  1606.                   txbuf[2]);
  1607.                 if ((txbuf[0] != 032)    /* .ARC file */
  1608.                  && (txbuf[0] != 0x1f)    /* .Z file */
  1609.                  && (txbuf[0] != 0x1c)    /* .LHZ file */
  1610.                  && strncmp(txbuf, "ZOO", 3)
  1611.                  && strncmp(txbuf, "GIF", 3)
  1612.                  && (txbuf[2] != 3))    /* .ZIP file */
  1613.                     Txfcs32 = 2;
  1614.                 else if ( !(Lztrans & ZTRLE))
  1615.                     Txfcs32 = 1;
  1616.             }
  1617.             /* GEnie binary can't seek to byte */
  1618.             if (Binfile) {
  1619.                 Rxpos &= ~127L;
  1620.             }
  1621. #endif
  1622.             if (fseek(in, Rxpos, 0))
  1623.                 return ERROR;
  1624.             Lastsync = (bytcnt = Txpos = Lrxpos = Rxpos) -1;
  1625.             return zsendfdata();
  1626.         }
  1627.     }
  1628. }
  1629.  
  1630. /* Send the data in the file */
  1631. zsendfdata()
  1632. {
  1633.     register c, e, n;
  1634.     register newcnt;
  1635.     register long tcount = 0;
  1636.     int junkcount;        /* Counts garbage chars received by TX */
  1637.     static int tleft = 6;    /* Counter for test mode */
  1638.  
  1639.     junkcount = 0;
  1640.     Beenhereb4 = FALSE;
  1641. somemore:
  1642.     if (setjmp(intrjmp)) {
  1643. waitack:
  1644.         junkcount = 0;
  1645.         c = getinsync(0);
  1646. gotack:
  1647.         switch (c) {
  1648.         default:
  1649.         case ZCAN:
  1650.             fclose(in);
  1651.             return ERROR;
  1652.         case ZSKIP:
  1653.             fclose(in);
  1654.             return c;
  1655.         case ZACK:
  1656.         case ZRPOS:
  1657.             break;
  1658.         case ZRINIT:
  1659.             return OK;
  1660.         }
  1661. #ifdef READCHECK
  1662.         /*
  1663.          * If the reverse channel can be tested for data,
  1664.          *  this logic may be used to detect error packets
  1665.          *  sent by the receiver, in place of setjmp/longjmp
  1666.          *  rdchk(fd) returns non 0 if a character is available
  1667.          */
  1668.         while (rdchk(0)) {
  1669. #ifdef EATSIT
  1670.             switch (checked)
  1671. #else
  1672.             switch (readline(1))
  1673. #endif
  1674.             {
  1675.             case CAN:
  1676.             case ZPAD:
  1677.                 c = getinsync(1);
  1678.                 goto gotack;
  1679.             case XOFF:        /* Wait a while for an XON */
  1680.             case XOFF|0200:
  1681.                 readline(100);
  1682.             }
  1683.         }
  1684. #endif
  1685.     }
  1686.  
  1687.     if ( !Fromcu)
  1688.         signal(SIGINT, onintr);
  1689.     newcnt = Rxbuflen;
  1690.     Txwcnt = 0;
  1691.     stohdr(Txpos);
  1692.     zsbhdr(4, ZDATA, Txhdr);
  1693.  
  1694.     /*
  1695.      * Special testing mode.  This should force receiver to Attn,ZRPOS
  1696.      *  many times.  Each time the signal should be caught, causing the
  1697.      *  file to be started over from the beginning.
  1698.      */
  1699.     if (Test) {
  1700.         if ( --tleft)
  1701.             while (tcount < 20000) {
  1702.                 printf(qbf); fflush(stdout);
  1703.                 tcount += strlen(qbf);
  1704. #ifdef READCHECK
  1705.                 while (rdchk(0)) {
  1706. #ifdef EATSIT
  1707.                     switch (checked)
  1708. #else
  1709.                     switch (readline(1))
  1710. #endif
  1711.                     {
  1712.                     case CAN:
  1713.                     case ZPAD:
  1714. #ifdef TCFLSH
  1715.                         ioctl(0, TCFLSH, 1);
  1716. #endif
  1717.                         goto waitack;
  1718.                     case XOFF:    /* Wait for XON */
  1719.                     case XOFF|0200:
  1720.                         readline(100);
  1721.                     }
  1722.                 }
  1723. #endif
  1724.             }
  1725.         signal(SIGINT, SIG_IGN); canit();
  1726.         sleep(3); purgeline(); mode(0);
  1727.         printf("\nsz: Tcount = %ld\n", tcount);
  1728.         if (tleft) {
  1729.             printf("ERROR: Interrupts Not Caught\n");
  1730.             exit(1);
  1731.         }
  1732.         exit(SS_NORMAL);
  1733.     }
  1734.  
  1735.     do {
  1736.         n = zfilbuf();
  1737.         if (Eofseen)
  1738.             e = ZCRCE;
  1739.         else if (junkcount > 3)
  1740.             e = ZCRCW;
  1741.         else if (bytcnt == Lastsync)
  1742.             e = ZCRCW;
  1743.         else if (Rxbuflen && (newcnt -= n) <= 0)
  1744.             e = ZCRCW;
  1745.         else if (Txwindow && (Txwcnt += n) >= Txwspac) {
  1746.             Txwcnt = 0;  e = ZCRCQ;
  1747.         } else
  1748.             e = ZCRCG;
  1749.         if (Verbose>1)
  1750.             fprintf(stderr, "\r%7ld ZMODEM%s    ",
  1751.               Txpos, Crc32t?" CRC-32":"");
  1752.         zsdata(txbuf, n, e);
  1753.         bytcnt = Txpos += n;
  1754.         if (e == ZCRCW)
  1755.             goto waitack;
  1756. #ifdef READCHECK
  1757.         /*
  1758.          * If the reverse channel can be tested for data,
  1759.          *  this logic may be used to detect error packets
  1760.          *  sent by the receiver, in place of setjmp/longjmp
  1761.          *  rdchk(fd) returns non 0 if a character is available
  1762.          */
  1763.         fflush(stdout);
  1764.         while (rdchk(0)) {
  1765. #ifdef EATSIT
  1766.             switch (checked)
  1767. #else
  1768.             switch (readline(1))
  1769. #endif
  1770.             {
  1771.             case CAN:
  1772.             case ZPAD:
  1773.                 c = getinsync(1);
  1774.                 if (c == ZACK)
  1775.                     break;
  1776. #ifdef TCFLSH
  1777.                 ioctl(0, TCFLSH, 1);
  1778. #endif
  1779.                 /* zcrce - dinna wanna starta ping-pong game */
  1780.                 zsdata(txbuf, 0, ZCRCE);
  1781.                 goto gotack;
  1782.             case XOFF:        /* Wait a while for an XON */
  1783.             case XOFF|0200:
  1784.                 readline(100);
  1785.             default:
  1786.                 ++junkcount;
  1787.             }
  1788.         }
  1789. #endif    /* READCHECK */
  1790.         if (Txwindow) {
  1791.             while ((tcount = Txpos - Lrxpos) >= Txwindow) {
  1792.                 vfile("%ld window >= %u", tcount, Txwindow);
  1793.                 if (e != ZCRCQ)
  1794.                     zsdata(txbuf, 0, e = ZCRCQ);
  1795.                 c = getinsync(1);
  1796.                 if (c != ZACK) {
  1797. #ifdef TCFLSH
  1798.                     ioctl(0, TCFLSH, 1);
  1799. #endif
  1800.                     zsdata(txbuf, 0, ZCRCE);
  1801.                     goto gotack;
  1802.                 }
  1803.             }
  1804.             vfile("window = %ld", tcount);
  1805.         }
  1806.     } while (!Eofseen);
  1807.     if ( !Fromcu)
  1808.         signal(SIGINT, SIG_IGN);
  1809.  
  1810.     for (;;) {
  1811.         stohdr(Txpos);
  1812.         zsbhdr(4, ZEOF, Txhdr);
  1813.         switch (getinsync(0)) {
  1814.         case ZACK:
  1815.             continue;
  1816.         case ZRPOS:
  1817.             goto somemore;
  1818.         case ZRINIT:
  1819.             return OK;
  1820.         case ZSKIP:
  1821.             fclose(in);
  1822.             return c;
  1823.         default:
  1824.             fclose(in);
  1825.             return ERROR;
  1826.         }
  1827.     }
  1828. }
  1829.  
  1830. /*
  1831.  * Respond to receiver's complaint, get back in sync with receiver
  1832.  */
  1833. getinsync(flag)
  1834. {
  1835.     register c;
  1836.  
  1837.     for (;;) {
  1838.         if (Test) {
  1839.             printf("\r\n\n\n***** Signal Caught *****\r\n");
  1840.             Rxpos = 0; c = ZRPOS;
  1841.         } else
  1842.             c = zgethdr(Rxhdr, 0);
  1843.         switch (c) {
  1844.         case ZCAN:
  1845.         case ZABORT:
  1846.         case ZFIN:
  1847.         case TIMEOUT:
  1848.             return ERROR;
  1849.         case ZRPOS:
  1850.             /* ************************************* */
  1851.             /*  If sending to a buffered modem, you  */
  1852.             /*   might send a break at this point to */
  1853.             /*   dump the modem's buffer.         */
  1854.             clearerr(in);    /* In case file EOF seen */
  1855.             if (fseek(in, Rxpos, 0))
  1856.                 return ERROR;
  1857.             Eofseen = 0;
  1858.             bytcnt = Lrxpos = Txpos = Rxpos;
  1859. #ifndef GENIE
  1860.             if (Lastsync == Rxpos) {
  1861.                 if (++Beenhereb4 > 4)
  1862.                     if (blklen > 32)
  1863.                         blklen /= 2;
  1864.             }
  1865. #endif
  1866.             Lastsync = Rxpos;
  1867.             return c;
  1868.         case ZACK:
  1869.             Lrxpos = Rxpos;
  1870.             if (flag || Txpos == Rxpos)
  1871.                 return ZACK;
  1872.             continue;
  1873.         case ZRINIT:
  1874.         case ZSKIP:
  1875.             fclose(in);
  1876.             return c;
  1877.         case ERROR:
  1878.         default:
  1879.             zsbhdr(4, ZNAK, Txhdr);
  1880.             continue;
  1881.         }
  1882.     }
  1883. }
  1884.  
  1885.  
  1886. /* Say "bibi" to the receiver, try to do it cleanly */
  1887. saybibi()
  1888. {
  1889.     for (;;) {
  1890.         stohdr(0L);        /* CAF Was zsbhdr - minor change */
  1891.         zshhdr(4, ZFIN, Txhdr);    /*  to make debugging easier */
  1892.         switch (zgethdr(Rxhdr, 0)) {
  1893.         case ZFIN:
  1894.             sendline('O'); sendline('O'); flushmo();
  1895.         case ZCAN:
  1896.         case TIMEOUT:
  1897.             return;
  1898.         }
  1899.     }
  1900. }
  1901.  
  1902. /* Local screen character display function */
  1903. bttyout(c)
  1904. {
  1905.     if (Verbose)
  1906.         putc(c, stderr);
  1907. }
  1908.  
  1909. /* Send command and related info */
  1910. zsendcmd(buf, blen)
  1911. char *buf;
  1912. {
  1913.     register c;
  1914.     long cmdnum;
  1915.  
  1916. #ifdef GENIE
  1917.     cmdnum = 69;
  1918. #else
  1919.     cmdnum = getpid();
  1920. #endif
  1921.     errors = 0;
  1922.     for (;;) {
  1923.         stohdr(cmdnum);
  1924.         Txhdr[ZF0] = Cmdack1;
  1925.         zsbhdr(4, ZCOMMAND, Txhdr);
  1926.         zsdata(buf, blen, ZCRCW);
  1927. listen:
  1928.         Rxtimeout = 100;        /* Ten second wait for resp. */
  1929.         Usevhdrs = 0;        /* Allow rx to send fixed len headers */
  1930.         c = zgethdr(Rxhdr, 1);
  1931.  
  1932.         switch (c) {
  1933.         case ZRINIT:
  1934.             goto listen;    /* CAF 8-21-87 */
  1935.         case ERROR:
  1936.         case GCOUNT:
  1937.         case TIMEOUT:
  1938.             if (++errors > Cmdtries)
  1939.                 return ERROR;
  1940.             continue;
  1941.         case ZCAN:
  1942.         case ZABORT:
  1943.         case ZFIN:
  1944.         case ZSKIP:
  1945.         case ZRPOS:
  1946.             return ERROR;
  1947.         default:
  1948.             if (++errors > 20)
  1949.                 return ERROR;
  1950.             continue;
  1951.         case ZCOMPL:
  1952.             Exitcode = Rxpos;
  1953.             saybibi();
  1954.             return OK;
  1955.         case ZRQINIT:
  1956. #ifdef vax11c        /* YAMP :== Yet Another Missing Primitive */
  1957.             return ERROR;
  1958. #else
  1959.             vfile("******** RZ *******");
  1960.             system("rz");
  1961.             vfile("******** SZ *******");
  1962.             goto listen;
  1963. #endif
  1964.         }
  1965.     }
  1966. }
  1967.  
  1968. /*
  1969.  * If called as sb use YMODEM protocol
  1970.  */
  1971. chkinvok(s)
  1972. char *s;
  1973. {
  1974.     register char *p;
  1975.  
  1976.     p = s;
  1977.     while (*p == '-')
  1978.         s = ++p;
  1979.     while (*p)
  1980.         if (*p++ == '/')
  1981.             s = p;
  1982.     if (*s == 'v') {
  1983.         Verbose=1; ++s;
  1984.     }
  1985.     Progname = s;
  1986.     if (s[0]=='s' && s[1]=='b') {
  1987.         Nozmodem = TRUE; blklen=1024;
  1988.     }
  1989.     if (s[0]=='s' && s[1]=='x') {
  1990.         Modem2 = TRUE;
  1991.     }
  1992. }
  1993.  
  1994. #ifdef STAT
  1995. countem(argc, argv)
  1996. register char **argv;
  1997. {
  1998.     register c;
  1999.     struct stat f;
  2000.  
  2001.     for (Totalleft = 0, Filesleft = 0; --argc >=0; ++argv) {
  2002.         f.st_size = -1;
  2003.         if (Verbose>2) {
  2004.             fprintf(stderr, "\nCountem: %03d %s ", argc, *argv);
  2005.             fflush(stderr);
  2006.         }
  2007.         if (access(*argv, 04) >= 0 && stat(*argv, &f) >= 0) {
  2008.             c = f.st_mode & S_IFMT;
  2009.             if (c != S_IFDIR && c != S_IFBLK) {
  2010.                 ++Filesleft;  Totalleft += f.st_size;
  2011.             }
  2012.         }
  2013.         if (Verbose>2)
  2014.             fprintf(stderr, " %ld", f.st_size);
  2015.     }
  2016.     if (Verbose>2)
  2017.         fprintf(stderr, "\ncountem: Total %d %ld\n",
  2018.           Filesleft, Totalleft);
  2019. }
  2020. #else
  2021. countem(argc, argv)
  2022. register char **argv;
  2023. {
  2024.     register c;
  2025.     register char *p;
  2026.     long size;
  2027.  
  2028.     for (Totalleft = 0, Filesleft = 0; --argc >=0; ++argv) {
  2029.         size = -1;
  2030.         if (Verbose>2) {
  2031.             fprintf(stderr, "\nCountem: %03d %s ", argc, *argv);
  2032.             fflush(stderr);
  2033.         }
  2034.         ++Filesleft;  
  2035. #ifdef XARGSFILE
  2036.         /* Look for file length in third colon sep field */
  2037.         for (p = *argv; *p; ++p) {
  2038.             if (*p == ':') {
  2039.                 for (++p; *p; ++p) {
  2040.                     if (*p == ':') {
  2041.                         ++p;
  2042.                         size = atol(p);
  2043.                         Totalleft += size;
  2044.                         break;
  2045.                     }
  2046.                 }
  2047.             break;
  2048.             }
  2049.         }
  2050. #endif
  2051.  
  2052.         if (Verbose>2)
  2053.             fprintf(stderr, " %ld", size);
  2054.     }
  2055.     if (Verbose>2)
  2056.         fprintf(stderr, "\ncountem: Total %d %ld\n",
  2057.           Filesleft, Totalleft);
  2058. }
  2059. #endif
  2060.  
  2061. chartest(m)
  2062. {
  2063.     register n;
  2064.  
  2065.     mode(m);
  2066.     printf("\r\n\nCharacter Transparency Test Mode %d\r\n", m);
  2067.     printf("If Pro-YAM/ZCOMM is not displaying ^M hit ALT-V NOW.\r\n");
  2068.     printf("Hit Enter.\021");  fflush(stdout);
  2069.     readline(500);
  2070.  
  2071.     for (n = 0; n < 256; ++n) {
  2072.         if (!(n%8))
  2073.             printf("\r\n");
  2074.         printf("%02x ", n);  fflush(stdout);
  2075.         sendline(n);    flushmo();
  2076.         printf("  ");  fflush(stdout);
  2077.         if (n == 127) {
  2078.             printf("Hit Enter.\021");  fflush(stdout);
  2079.             readline(500);
  2080.             printf("\r\n");  fflush(stdout);
  2081.         }
  2082.     }
  2083.     printf("\021\r\nEnter Characters, echo is in hex.\r\n");
  2084.     printf("Hit SPACE or pause 40 seconds for exit.\r\n");
  2085.  
  2086.     while (n != TIMEOUT && n != ' ') {
  2087.         n = readline(400);
  2088.         printf("%02x\r\n", n);
  2089.         fflush(stdout);
  2090.     }
  2091.     printf("\r\nMode %d character transparency test ends.\r\n", m);
  2092.     fflush(stdout);
  2093. }
  2094.  
  2095. /* End of sz.c */
  2096.